import got from "got";
import { pay } from "./utils/pay.js";
import { coverPayLink } from "./utils/payLink.js";
import config from "./config.js";
import { cookieJar, Cookie } from "./utils/cookie.js";
import { sleep, log, logError } from "./utils/util.js";

const url = "https://mclient.alipay.com";

const configCookies = config.cookie.split(";").map(Cookie.parse);

const cookieStr = await cookieJar.getCookieString(url);
if (cookieStr) {
  log(`使用缓存cookie`);
} else {
  log(`cookie无缓存，使用config中cookie`);
  for (const cookie of configCookies) {
    await cookieJar.setCookie(cookie, url);
  }
}

log("cookie: ", await cookieJar.getCookieString(url));

const deviceIds =
  typeof config.deviceId === "string" ? [config.deviceId] : config.deviceId;
// 开始支付
deviceIds.forEach((deviceId) => {
  pollPay(deviceId);
});

const lastOrderMap = {};

async function pollPay(deviceId) {
  while (true) {
    try {
      await payOrders(deviceId);
    } catch (e) {
      logError(e);
    } finally {
      await sleep(200);
    }
  }
}

export const applyPay = async (order, deviceId) => {
  await got({
    url: `${config.baseUrl}/api/AutoPay/Apply`,
    method: "GET",
    searchParams: {
      id: order.id,
      deviceId,
    },
  });
};

export const pushBarkMessage = async (message, order) => {
  let url = "";
  try {
    const payUrl = await coverPayLink(order.payBiz);
    const u = new URL(payUrl);
    const contextId = u.searchParams.get("session");
    url = `alipay://alipayclient/?%7B%22requestType%22%3A%22SafePay%22%2C%22fromAppUrlScheme%22%3A%22alipays%22%2C%22dataString%22%3A%22h5_route_token%3D%5C%22${contextId}%5C%22%26is_h5_route%3D%5C%22true%5C%22%22%7D`;
  } catch (e) {
    logError(e);
  }
  const content = "";
  log("推送bark", `message: ${message}`, `content: ${content}`);
  await got({
    url: `https://api.day.app/enwhFheR6WoaNaxtS9QX2E/${message}/${content}`,
    searchParams: { copy: content, level: "critical", volume: 5, url },
  });
};

let lastPayUrl = "";
let lastCookieTime = 0;

const refreshCookie = async () => {
  if (lastPayUrl) {
    await got({
      url: lastPayUrl,
      headers: {
        Referer: lastPayUrl,
        "User-Agent": config.userAgent,
      },
      cookieJar,
    }).catch((err) => logError("payUrl 保活", err.message));
  }
  await got({
    url: "https://mclient.alipay.com/index.htm",
    headers: {
      Referer: "https://mclient.alipay.com/index.htm",
      "User-Agent": config.userAgent,
    },
    cookieJar,
  }).catch((err) => logError("index 保活", err.message));
};

async function payOrders(deviceId) {
  const res = await got({
    url: `${config.baseUrl}/api/mcd/client/order/paying/list`,
    searchParams: {
      deviceNo: deviceId,
    },
  });
  const body = JSON.parse(res.body);
  const orders = body?.data || [];
  log(`${deviceId} 获取到${orders.length}条订单`);
  if (orders.length > 0) {
    for (const order of orders) {
      if (lastOrderMap[deviceId] === order.orderId) {
        continue;
      }
      const logPrefixes = `[${deviceId},${order.orderId},${order.sign},`;
      try {
        log(`${logPrefixes}申请支付`);
        applyPay(order, deviceId).catch((e) =>
          logError(`${logPrefixes}申请支付失败`, e),
        );

        const payUrl = await coverPayLink(order.payBiz);
        log(`${logPrefixes}支付地址:${payUrl}`);

        log(`${logPrefixes}开始支付`);
        await pay(payUrl, config.payPwd);

        lastOrderMap[deviceId] = order.orderId;

        lastPayUrl = payUrl;
        lastCookieTime = Date.now();
        log(`${logPrefixes}支付成功`);
      } catch (err) {
        logError(`${logPrefixes}失败`, err);
        const errMsg = err.message || "";

        if (errMsg.includes("超时")) {
          cookieJar.removeAllCookiesSync();
          log(`cookie失效，已清空，请重新登录`);
        }
        pushBarkMessage(`${logPrefixes},${errMsg}`, order)
          .catch((e) => logError(`${logPrefixes}${errMsg},推送消息失败`, e))
          .finally(() => {
            if (
              errMsg.includes("超时") ||
              errMsg.includes("支付密码不正确")
              // || errMsg.includes("验证码")
            ) {
              process.exit(1);
            }
          });
      }
    }
  } else {
    const needRefreshCookie = Date.now() - lastCookieTime > 60 * 1000;
    if (needRefreshCookie) {
      await refreshCookie();
      lastCookieTime = Date.now();
      log("cookie保活执行");
    }
  }
}
